/*
 * @file hme_dma.h
 * @brief HME HeaderFile
 * @version 0.1
 * @date 01. March 2021
 */

#ifndef __HME_DMA_H__
#define __HME_DMA_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "hme_conf.h"
#include "BasicDataType.h"

#define DMA_MAX_CHANNEL_NUM                 8

#ifdef HME_H7
#define DMA_MAX_BLOCKTS_ITEM				2047
#define DMA_TOTAL_CHANNEL_CNT				1
#endif

#ifdef HME_P2
#define DMA_MAX_BLOCKTS_ITEM				2047
#define DMA_TOTAL_CHANNEL_CNT				1
#endif

#ifdef HME_P3
#define DMA_MAX_BLOCKTS_ITEM				4095
#define DMA_TOTAL_CHANNEL_CNT				4
#endif


/** @defgroup DMA_Int
  * @{
  */
#define DMA_Int_TfrComplete                	0x00000001    
#define DMA_Int_Err                       	0x00000002
#define DMA_Int_All                        	0x00000003

#define IS_DMA_INT(INT)        (((INT) != 0) && (((INT) & ~DMA_Int_All) == 0))
/**
  * @}
  */ 


/****d* dmac.data/dw_dmac_transfer_flow
 * DESCRIPTION
 *  This data type is used for selecting the transfer flow device
 *  (memory or peripheral device) and for setting the flow control
 *  device for the DMA transfer when using the specified driver
 *  API functions.
 * NOTES
 *  This data type relates directly to the following DMA Controller
 *  register(s) / bit field(s): (x = channel number)
 *    - CTLx.TT_FC
 * SEE ALSO
 *  dw_dmac_setMemPeriphFlowCtl(), dw_dmac_getMemPeriphFlowCtl()
 * SOURCE
 */
enum dw_dmac_transfer_flow {
    Dmac_mem2mem_dma    = 0x0, /* mem to mem - DMAC   flow ctlr */
    Dmac_mem2prf_dma    = 0x1, /* mem to prf - DMAC   flow ctlr */
    Dmac_prf2mem_dma    = 0x2, /* prf to mem - DMAC   flow ctlr */
    Dmac_prf2prf_dma    = 0x3, /* prf to prf - DMAC   flow ctlr */
    Dmac_prf2mem_prf    = 0x4, /* prf to mem - periph flow ctlr */
    Dmac_prf2prf_srcprf = 0x5, /* prf to prf - source flow ctlr */
    Dmac_mem2prf_prf    = 0x6, /* mem to prf - periph flow ctlr */
    Dmac_prf2prf_dstprf = 0x7  /* prf to prf - dest   flow ctlr */
};
/*****/

/****d* dmac.data/dw_dmac_burst_trans_length
 * DESCRIPTION
 *  This data type is used for selecting the burst transfer length
 *  on the source and/or destination of a DMA channel when using the
 *  specified driver API functions. These transfer length values do
 *  not relate to the AMBA HBURST parameter.
 * NOTES
 *  This data type relates directly to the following DMA Controller
 *  register(s) / bit field(s): (x = channel number)
 *    - CTLx.SRC_MSIZE, CTLx.DEST_MSIZE
 * SEE ALSO
 *  dw_dmac_setBurstTransLength(), dw_dmac_getBurstTransLength()
 * SOURCE
 */
enum dw_dmac_burst_trans_length {
    Dmac_msize_1   = 0x0,
    Dmac_msize_4   = 0x1,
    Dmac_msize_8   = 0x2,
    Dmac_msize_16  = 0x3,
    Dmac_msize_32  = 0x4,
    Dmac_msize_64  = 0x5,
    Dmac_msize_128 = 0x6,
    Dmac_msize_256 = 0x7
};
/*****/

/****d* dmac.data/dw_dmac_address_increment
 * DESCRIPTION
 *  This data type is used for selecting the address increment
 *  type for the source and/or destination on a DMA channel when using
 *  the specified driver API functions.
 * NOTES
 *  This data type relates directly to the following DMA Controller
 *  register(s) / bit-field(s): (x = channel number)
 *    - CTLx.SINC, CTLx.DINC
 * SEE ALSO
 *  dw_dmac_setAddressInc(), dw_dmac_getAddressInc()
 * SOURCE
 */
enum dw_dmac_address_increment {
    Dmac_addr_increment = 0x0,
    Dmac_addr_decrement = 0x1,
    Dmac_addr_nochange  = 0x2
};
/*****/

/****d* dmac.data/dw_dmac_transfer_width
 * DESCRIPTION
 *  This data type is used for selecting the transfer width for the
 *  source and/or destination on a DMA channel when using the specified
 *  driver API functions. This data type maps directly to the AMBA AHB
 *  HSIZE parameter.
 * NOTES
 *  This data type relates directly to the following DMA Controller
 *  register(s) / bit field(s): (x = channel number)
 *    - CTLx.SRC_TR_WIDTH, CTLx.DST_TR_WIDTH
 * SEE ALSO
 *  dw_dmac_setTransWidth(), dw_dmac_getTransWidth()
 * SOURCE
 */
enum dw_dmac_transfer_width {
    Dmac_trans_width_8   = 0x0,
    Dmac_trans_width_16  = 0x1,
    Dmac_trans_width_32  = 0x2,
    Dmac_trans_width_64  = 0x3,
    Dmac_trans_width_128 = 0x4,
    Dmac_trans_width_256 = 0x5
};
/*****/


enum dw_dmac_handshake_number {
    Dmac_handshake_number_i2c0_tx   = 0,
	Dmac_handshake_number_i2c0_rx	= 1,
	Dmac_handshake_number_i2c1_tx   = 2,
	Dmac_handshake_number_i2c1_rx   = 3,
	Dmac_handshake_number_uart0_tx  = 6,
	Dmac_handshake_number_uart0_rx  = 7,
	Dmac_handshake_number_uart1_tx  = 8,
	Dmac_handshake_number_uart1_rx  = 9,
	Dmac_handshake_number_spi0_tx   = 10,
	Dmac_handshake_number_spi0_rx   = 11,
	Dmac_handshake_number_spi1_tx   = 12,
	Dmac_handshake_number_spi1_rx   = 13,
	Dmac_handshake_number_qspi_tx   = 14,
	Dmac_handshake_number_qspi_rx   = 15
};

typedef enum HME_DMAC_CFGREG {
    HME_DMAC_DISABLED,
    HME_DMAC_ENABLED
} HME_DMAC_CFGREG;  
  
typedef struct {
	HME_DMAC_CFGREG DMA_ENABLE;
	uint32_t *SRC_ADDR;
	uint32_t *TAR_ADDR;
	uint8_t transtype;
	uint8_t SINC;
	uint8_t DINC;
	uint32_t BLOCK_TS;
	uint8_t SRC_MSIZE;
	uint8_t DEST_MSIZE;
	uint8_t SRC_TR_WIDTH;
	uint8_t DST_TR_WIDTH;
	uint8_t DST_REQ_NUM;
	uint8_t SRC_REQ_NUM;
	uint8_t TRANS_DIR;
} HME_DMAC_InitTypeDef;  


/**
  * @brief  Descriptor structure
	*	@note		DMA requires users provides a list of descriptors to operation.
	*					Meanwhile, memory occupied by descriptors should be in physical
	*					memory and keep valid during DMA transfer.
	*/ 
typedef struct {                      
	uint32_t srcAddr;                  /*!< source address 														*/		
	uint32_t dstAddr;                  /*!< destination address 											*/	
	uint32_t number;                   /*!< block byte number, no more than 8K Bytes 	*/
	uint32_t nextBlock;                /*!< next block descriptor 										*/
	uint32_t padding;                  /*!< Nonsense, only used to fill 							*/
} BLOCK_DESC;
	
/**
  * @brief  Deinitializes the DMA peripheral registers to their default reset values.
	* @param[in] None
  * @retval None
	*/ 
void DMA_DeInit(void);

/**
  * @brief  DMA channel initialization
  * @note   This function should be called at first before any other interfaces.
	* @param[in] ch Channel number of DMA, invalid range is 0 - 7
	* @param[in] priority Channel priority of DMA, invalid range is 0 - 7 and 7 is highest.
  *            The low-number channel is granted at frist if same priority
	* @retval None
	*/ 
void DMA_Init(uint8_t ch, uint8_t priority);

/**
  * @brief  Enable or disable DMA interrupt. 
  * @param[in] ch Channel number of DMA, invalid range is 0 - 7
	* @param[in] Int interrupt mask bits, which can be the combination of @ref DMA_Int
	* @param[in] Enable The bit indicates if specific interrupts are enable or not
  * @retval None
	*/ 
void DMA_ITConfig(uint8_t ch, uint32_t Int, BOOL enable);

/**
  * @brief  Check specific interrupts are set or not 
  * @param[in] ch Channel number of DMA, invalid range is 0 - 7
	* @param[in] Int interrupt mask bits, which can be the combination of @ref DMA_Int
  * @retval BOOL The bit indicates if specific interrupts are set or not
	*/
BOOL DMA_GetITStatus(uint8_t ch, uint32_t Int);

/**
  * @brief  Clear specific interrupts
  * @param[in] ch Channel number of DMA, invalid range is 0 - 7
	* @param[in] Int interrupt mask bits, which can be the combination of @ref DMA_Int
  * @retval None
	*/
void DMA_ClearITPendingBit(uint8_t ch, uint32_t Int);

/**
  * @brief  DMA transfer
	* @note		Make sure that memory occupied by descriptors should be in physical
	*					memory and keep valid before DMA transfer is finished (Return false by
	*					calling DMA_IsBusy after DMA transfer started).
  * @param[in] ch Channel number of DMA, invalid range is 0 - 7
	* @param[in] blockList A pointer to header of list of BLOCK_DESC
  * @retval BOOL The bit indicates if DMA channel begins to transfer
	* @see		DMA_IsBusy
	*/
BOOL DMA_Transfer(uint8_t ch, BLOCK_DESC *blockList);

/**
  * @brief  DMA is busy or not
  * @param[in] ch Channel number of DMA, invalid range is 0 - 7
	* @retval BOOL The bit indicates if DMA channel is busy or not
	*/ 
BOOL DMA_IsBusy(uint8_t ch);

BOOL HME_DMA_Init(uint8_t ch, HME_DMAC_InitTypeDef *DMAC_Init);

void HME_DMA_CFGREG(DMAC_Type *DMACx,uint32_t value);

void HME_DMA_CHENREG_ENABLE(uint8_t ch);

void HME_DMA_CHENREG_DISABLE(uint8_t ch);

void HME_DMA_DISABLE_CH_INTR(DMAC_Type *DMACx,uint8_t ch);

#ifdef __cplusplus
}
#endif

#endif /* __CMEM7_DMA_H */
